package com.navercorp.pinpoint.plugin.seasar.reqeust;

import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod;
import com.navercorp.pinpoint.bootstrap.instrument.Instrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformCallback;
import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformTemplate;
import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformTemplateAware;
import com.navercorp.pinpoint.bootstrap.interceptor.BasicMethodInterceptor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext;

import java.security.ProtectionDomain;

import static com.navercorp.pinpoint.common.util.VarArgs.va;

/**
 * Seasar请求记录插件
 * Created by Irany 2018/8/23 10:08
 */
public class SeasarRequestPlugin implements ProfilerPlugin, TransformTemplateAware {
    @Override
    public void setTransformTemplate(TransformTemplate transformTemplate) {
        this.transformTemplate = transformTemplate;
    }

    @Override
    public void setup(ProfilerPluginSetupContext context) {
        log.info("setup addRequestTransformCallback");
        addRequestTransformCallback(context);

    }


    public void addRequestTransformCallback(ProfilerPluginSetupContext context) {
        log.info("addRequestTransformCallback...");
        transformTemplate.transform(SeasarRequestConstants.REQUEST_CLASS_PATH, new TransformCallback() {
            @Override
            public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> aClass, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
                InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);
                log.info("className:{},targetName:{}",className,target.getName());
                InstrumentMethod doFilter = target.getDeclaredMethod("doFilter", "javax.servlet.ServletRequest", "javax.servlet.ServletResponse","javax.servlet.FilterChain");
                log.info("addInterceptor init...");
                doFilter.addInterceptor(BasicMethodInterceptor.class.getName(), va(SeasarRequestConstants.SEASAR_REQUSET_SERVICE_TYPE));
                log.info("addInterceptor complete");
                return target.toBytecode();
            }
        });

    }

    private final PLogger log = PLoggerFactory.getLogger(getClass());

    private TransformTemplate transformTemplate;
}
